// ==UserScript
// @name          MSDN Better View Core
// @namespace     http://userscripts.org/scripts/show/167562
// @description   Adjusts layout of the MSDN Library Lightweight View to be classic-like style.
// @include       http://msdn.microsoft.com/*
// @include       https://msdn.microsoft.com/*
// @grant         none
// @version       2013.8.5
// ==/UserScript==

var customCss = document.createElement("link");
customCss.rel = "stylesheet";
customCss.type = "text/css";

if (typeof variable === 'undefined') {
	customCss.href = "http://msdn-library-better-view.googlecode.com/git/msdn-better-view.css";
}
else {
	customCss.href = customCssHref;
}

document.getElementsByTagName("head")[0].appendChild(customCss);

//var jqScript = document.createElement('script');
//jqScript.src = 'http://code.jquery.com/jquery-1.9.1.min.js';
//jqScript.onload = onJqueryReady;

//document.getElementsByTagName("head")[0].appendChild(jqScript);
//onJqueryReady();

// test pages:
// http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa511260.aspx
// http://msdn.microsoft.com/en-us/library/ms668604.aspx
// http://msdn.microsoft.com/en-us/library/ms229042.aspx

var detectionTries = 0;
var enhancedFeaturesEnabled = false;
var backedUpBodyMarginTop = null;

(function() {
	detectJQueryReady();
})();

function detectJQueryReady() {
	var isReady = false;
	try {
		if (jQuery || detectionTries > 30) {
			isReady = true;
		}
	}
	catch (e) {
		// ReferenceError
	}
	
	if (isReady) {
		onJqueryReady();
	}
	else {
		window.setTimeout(detectJQueryReady, 100);
		++detectionTries;
	}
}


function getHeader() {
	var header = $("body.library #ux-header");
	
	if (!header.length) {
		header = $("body.library .ux-header");
	}
	
	return header;
}


function initEnhancedFeatures() {
	if (enhancedFeaturesEnabled) {
		return;
	}
	
	enhancedFeaturesEnabled = true;
	var pageTitle = $("body.library #content h1.title").first();
	
	var headerToggler = $("<a>").attr("href", "#").text("Toggle Header");
	headerToggler.css({
		"float": "right",
		"background": "#fff"
	});
	headerToggler.click(function() {
		var header = getHeader();
		header.toggle();
		localStorage.setItem("header-visible", header.is(":visible"));
		fixLayout();
	});
	
	pageTitle.before(headerToggler);
}


function onJqueryReady() {
	$(document).ready(function() {
		fixLayout();
		initEnhancedFeatures();
		$(window).resize(fixLayout);
		window.setTimeout(fixLayout, 500);

		window.setTimeout(autoExpand, 1000);
	});

	$(document).load(function() {
		autoExpand();
	});
}


function fixLayout() {
	var leftNav = $("body.library #leftNav");
	var content = $("body.library #content");
	var body = $("body.library #body");
	
	var header = getHeader();
	
	// header toggle
	if (localStorage.getItem("header-visible") === "false") {
		header.hide();
	}
	
	// fix body top margin
	if (!header.is(":visible")) {
		// header hidden
		if (backedUpBodyMarginTop === null) {
			backedUpBodyMarginTop = body.css("margin-top");
		}
		
		body.css("margin-top", 0);
	}
	else if (backedUpBodyMarginTop !== null) {
		body.css("margin-top", backedUpBodyMarginTop);
		backedUpBodyMarginTop = null;
	}
	
	// reorganize
	var altNav = header.find(".header-nav-container .header-nav");
	var headerBar = header.children(".header-top-bar");
	if (altNav && headerBar) {
		headerBar.children().first().after(altNav);
	}
	
	// fix leftnav size
	if (leftNav.attr("class")) {
		var leftNavClasses = leftNav.attr("class").split(/\s+/);
		for (var i = 0; i < leftNavClasses.length; ++i) {
			var curClass = leftNavClasses[i];

			if (curClass.indexOf("leftNavResize") >= 0) {
				leftNav.removeClass(curClass);
			}
		}
		
		content[0].style.removeProperty("margin-left");
	}
	
	// fixes header height
	
	
	header.height("auto");

	//var topOffset = header.outerHeight() + header.offset().top - 1;
	var topOffset = $("body.library #body").offset().top - 1;
	var navTopOffset = topOffset;

	if (header.next().attr("id") != "body") {
		navTopOffset = header.outerHeight() + header.offset().top - 1;
	}

	leftNav.css("top", navTopOffset);
	content.css("top", topOffset);
}


function autoExpand() {
	var nav = $("#tocnav");

	// expand up
	var currentNav = nav.children(".current");
	var level = getTocLevel(currentNav);

	if (level > 0) {
		var prevNav = currentNav;
		var prevLevel = level
		var isExpandable = false;

		do {
			prevNav = prevNav.prev();
			prevLevel = getTocLevel(prevNav);

			if (prevLevel < level) {
				if (isExpandable || isInAutoExpandScope(prevNav)) {
					isExpandable = true;
					setExpanded(prevNav);
				}

				level = prevLevel;
			}

		} while (level > 0 && prevNav.length > 0)
	}

	// expand down
	nav.children().each(function(index, el) {
		var navEl = $(el);

		if (isInAutoExpandScope(navEl)) {
			setExpanded(navEl);
		}
	});
}


function setExpanded(navEl) {
	var expander = navEl.children("a").first();

	if (!expander.hasClass("toc_expanded")) {
		expander.click();
	}
}


function isInAutoExpandScope(navEl) {
	var expand = ["constructor", "methods", "properties"];
	var expanderEl = navEl.children("a").first();
	var navTextEl = expanderEl.next();

	if (navTextEl.length == 0) {
		return false;
	}

	var navText = navTextEl.text().toLowerCase();

	for (var i = 0; i < expand.length; ++i) {
		if (navText.indexOf(expand[i]) >= 0) {
			// hit, expand
			return true;
		}
	}

	return false;
}


function getTocLevel(navEl) {
	var classes = navEl.attr("class").split(" ");

	for (var i = 0; i < classes.length; ++i) {
		if (classes[i].indexOf("toclevel") == 0) {
			return parseInt(classes[i].replace("toclevel", ""));
		}
	}
}
